﻿using System;
using System.Collections.Generic;
using Un4seen.Bass;

namespace Theta.Audio
{
    public class AudioEngine : IDisposable
    {
        List<AudioPlugin> _plugins;

        public bool IsInitialized { get; private set; }

        #region Initialization

        public bool Initialize()
        {
            return Initialize(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Core.WindowHandle, null);
        }

        public bool Initialize(int device)
        {
            return Initialize(device, 44100, BASSInit.BASS_DEVICE_DEFAULT, Core.WindowHandle, null);
        }

        public bool Initialize(int device, int sampleRate)
        {
            return Initialize(device, sampleRate, BASSInit.BASS_DEVICE_DEFAULT, Core.WindowHandle, null);
        }

        public bool Initialize(int device, int sampleRate, BASSInit flags)
        {
            return Initialize(device, sampleRate, flags, Core.WindowHandle, null);
        }

        public bool Initialize(int device, int sampleRate, BASSInit flags, IntPtr winHandle)
        {
            return Initialize(device, sampleRate, flags, winHandle, null);
        }

        public bool Initialize(int device, int sampleRate, BASSInit flags, IntPtr winHandle, Guid? guid)
        {
#if DEBUG
            BassNet.Registration("gintheninja@yahoo.com", "2X152932134322");
#endif
            //THANKS .NET FOR NOT ALLOWING ME TO PASS NULL TO GUID.
            bool init = (!guid.HasValue)
                            ? Bass.BASS_Init(device, sampleRate, flags, winHandle)
                            : Bass.BASS_Init(device, sampleRate, flags, winHandle, guid.Value);
            if (!init)
            {
                ThrowBassError();
            }

            _plugins = new List<AudioPlugin>();
            IsInitialized = init;
            return init;
        }
        #endregion
        
        public static void RegisterBass(string email, string apikey)
        {
            BassNet.Registration(email, apikey);
        }

        public void LoadPlugin(string dllName)
        {
            AudioPlugin plugin = new AudioPlugin(dllName);

            if(plugin.Load())
                _plugins.Add(plugin);
            else
                ThrowBassError();
        }

        public void Dispose()
        {
            foreach(AudioPlugin audioPlugin in _plugins)
            {
                audioPlugin.Dispose();
            }

            Bass.BASS_Free();
        }

        internal void ThrowBassError()
        {
            throw new Exception("There was an error while trying to use Bass: " + Bass.BASS_ErrorGetCode().ToString());
        }
    }
}
